/*
 * 一阶低通滤波器（也称为指数平滑滤波器）是最简单且高效的数字滤波算法之一，特别适合实时控制和传感器数据平滑处理。其核心思想是通过当前输入和前一次输出的加权平均来生成新的输出，让信号 "缓慢变化"，从而抑制高频噪声
 * 数学公式：y(n)=α⋅x(n)+(1−α)⋅y(n−1)
 * y(n) 是当前输出值
 * x(n) 是当前输入值
 * y(n-1) 是上一次输出值
 * α 是平滑系数（0 < α ≤ 1），决定滤波强度
 * α 的物理意义：α 越大：对新输入的响应越快，但滤波效果越弱（类似 "跟随" 输入）α 越小：滤波效果越强，但响应速度越慢（类似 "滞后" 输入）
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include "LPF1.h"


/**
 * 初始化一阶低通滤波器
 * @param filter 滤波器结构体指针
 * @param alpha 平滑系数，范围 (0, 1]
 * @return 状态码 (0 成功)
 */
static LPF1_Status WHT_LPF1_Init(WHT_LPF1_t *filter, float alpha)
{
    if (filter == NULL)
    {
        return LPF_ERROR_NULL_POINTER;
    }
    
    if (alpha <= 0.0f || alpha > 1.0f)
    {
        return LPF_ERROR_INVALID_ALPHA;
    }
    
    filter->alpha = alpha;
    filter->last_output = 0.0f;
    filter->init_flag = false;

    return LPF_OK;
}

/**
 * 基于时间常数初始化滤波器
 * @param filter 滤波器结构体指针
 * @param time_constant 时间常数（秒）
 * @param sample_rate 采样率（Hz）
 */
static LPF1_Status WHT_LPF1_Init_Time_Constant(WHT_LPF1_t *filter, float time_constant, float sample_rate)
{
    if (filter == NULL)
    {
        return LPF_ERROR_NULL_POINTER;
    }
        
    if (time_constant <= 0 || sample_rate <= 0)
    {
        return LPF_ERROR_INVALID_ALPHA;
    }
    
    float alpha = 1.0f - expf(-1.0f / (time_constant * sample_rate));

    return WHT_LPF1_Init(filter, alpha);
}

/**
 * 重置滤波器状态
 * @param filter 滤波器结构体指针
 */
static void WHT_LPF1_Reset(WHT_LPF1_t *filter)
{
    if (filter) filter->init_flag = false;
}

/**
 * 设置新的平滑系数
 * @param filter 滤波器结构体指针
 * @param alpha 新的平滑系数
 */
static LPF1_Status WHT_LPF1_Set_Alpha(WHT_LPF1_t *filter, float alpha)
{
    if (filter == NULL)
    {
        return LPF_ERROR_NULL_POINTER;
    }
    
    if (alpha <= 0.0f || alpha > 1.0f)
    {
        return LPF_ERROR_INVALID_ALPHA;
    }
    
    filter->alpha = alpha;

    return LPF_OK;
}

/**
 * 获取当前输出值（不更新状态）
 * @param filter 滤波器结构体指针
 * @return 当前输出值
 */
static float WHT_LPF1_Get_Current_Output(const WHT_LPF1_t *filter)
{
    return filter ? filter->last_output : 0.0f;
}

/**
 * 应用滤波器处理新数据点
 * @param filter 滤波器结构体指针
 * @param value 当前输入值
 * @return 滤波后的输出值
 */
static float WHT_LPF1_Apply_One(WHT_LPF1_t *filter, float value)
{   
    if (filter->init_flag == false)
    {
        filter->last_output = value;
        filter->init_flag = true;
    }
    else
    {
        filter->last_output = filter->alpha * value + (1.0f - filter->alpha) * filter->last_output;
    }
    
    return filter->last_output;
}

/**
 * 批量处理数据
 * @param filter 滤波器结构体指针
 * @param input 输入数组
 * @param output 输出数组（可等于输入数组）
 * @param size 数据点数
 */
static void WHT_LPF1_Apply_Multiple(WHT_LPF1_t *filter, float *input, float *output, size_t size)
{
    for(size_t i = 0; i < size; i++)
    {
        output[i] = WHT_LPF1_Apply_One(filter, input[i]);
    }
}



const WHT_LPF1_OPS_t WHT_LPF1_OPS =
{
    .init               = WHT_LPF1_Init,
    .init_time_constant = WHT_LPF1_Init_Time_Constant,
    .reset              = WHT_LPF1_Reset,
    .set_alpha          = WHT_LPF1_Set_Alpha,
    .get_current_output = WHT_LPF1_Get_Current_Output,
    .apply_one          = WHT_LPF1_Apply_One,
    .apply_multiple     = WHT_LPF1_Apply_Multiple,
};


// 使用示例
int main_LPF1(void)
{
    WHT_LPF1_t filter;
    float noisy_data[] = {1.0f, 1.2f, 1.5f, 1.3f, 1.1f, 0.9f, 0.8f, 0.7f, 0.9f, 1.2f, 1.5f};
    const int data_size = sizeof(noisy_data) / sizeof(noisy_data[0]);
    float filtered_data[data_size];
    
    // 初始化滤波器（两种方式）
    // 方式1：直接设置alpha
    if (WHT_LPF1_OPS.init(&filter, 0.4f) != LPF_OK)
    {
        printf("滤波器初始化失败\n");
        return -1;
    }
    
    // 方式2：基于时间常数（0.1秒）和采样率（10Hz）
    // WHT_LPF1_Init_Time_Constant(&filter, 0.1f, 10.0f);
    
    // 批量处理数据
    WHT_LPF1_OPS.apply_multiple(&filter, noisy_data, filtered_data, data_size);
    
    // 输出结果
    printf("原始数据: ");
    for (int i = 0; i < data_size; i++)
    {
        printf("%5.2f ", noisy_data[i]);
    }
    
    printf("\n滤波数据: ");
    for (int i = 0; i < data_size; i++)
    {
        printf("%5.2f ", filtered_data[i]);
    }
    printf("\n");
    
    // 获取当前状态
    printf("最终输出值: %.2f\n", WHT_LPF1_OPS.get_current_output(&filter));
    
    return 0;
}
